package com.zxx.mydesignplugin;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.os.Bundle;
import android.text.TextUtils;

import java.io.File;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import dalvik.system.DexClassLoader;

/**
 * 插件管理器
 *
 * @author zxx on 2021/7/21
 */
public class PluginManager {

    private static class Holder {
        static PluginManager manager = new PluginManager();
    }

    //单例
    public static PluginManager getInstance() {
        return Holder.manager;
    }

    private static Context mContext;
    private Map<String, PluginApk> sMap = new HashMap<>();

    public static void init(Context context) {
        mContext = context.getApplicationContext();
    }

    public PluginApk getPluginApk(String packageName) {
        return sMap.get(packageName);
    }

    /**
     * 加载插件APK
     *
     * @param apkPath 插件的绝对路径
     */
    public final void loadApk(String apkPath) {
        PackageInfo packageInfo = queryPackageInfo(apkPath);
        if (null == packageInfo || TextUtils.isEmpty(packageInfo.packageName)) {
            return;
        }
        PluginApk pluginApk = sMap.get(packageInfo.packageName);
        if (pluginApk == null) {
            pluginApk = createApk(apkPath);
            if (pluginApk != null) {
                pluginApk.packageInfo = packageInfo;

                sMap.put(packageInfo.packageName, pluginApk);
            } else {
                throw new NullPointerException("PluginApk is null!!");
            }
        }
    }

    private PackageInfo queryPackageInfo(String apkPath) {
        PackageInfo packageInfo = mContext.getPackageManager().getPackageArchiveInfo(apkPath,
                PackageManager.GET_ACTIVITIES | PackageManager.GET_SERVICES);

        if (packageInfo == null) {
            return null;
        }
        return packageInfo;
    }

    private PluginApk createApk(String apkPath) {
        PluginApk pluginApk = null;
        try {
            // AssetManager am = mContext.getResources().getAssets() ;
            AssetManager assetManager = AssetManager.class.newInstance();
            Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);

            addAssetPath.invoke(assetManager, apkPath);

            Resources pluginRes = new Resources(assetManager, mContext.getResources().getDisplayMetrics(),
                    mContext.getResources().getConfiguration());

            pluginApk = new PluginApk(pluginRes);

            //加载器
            pluginApk.classLoader = createDexClassLoader(apkPath);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return pluginApk;
    }

    private DexClassLoader createDexClassLoader(String apkPath) {
        File dexOutputDir = mContext.getDir("dex", Context.MODE_PRIVATE);
        DexClassLoader loader = new DexClassLoader(apkPath, dexOutputDir.getAbsolutePath(), null,
                mContext.getClassLoader());
        return loader;
    }

    // TODO : 覆写PluginActivity的对应方法
    public void startActivity(Intent intent) {
        Intent myIntent = new Intent(mContext, ActivityProxy.class);
        Bundle bundle = intent.getExtras();
        if (bundle == null || !bundle.containsKey(Constants.PLUGIN_CLASS_NAME)
                && !bundle.containsKey(Constants.PACKAGE_NAME)) {
            throw new IllegalArgumentException("没有设置插件的类路径和包名");
        }

        myIntent.putExtras(intent);
        myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        mContext.startActivity(myIntent);
    }

}
